#include <sys_head.h>

void *Tcp_Server_func(void *arg);

//定义一个全局变量的数组
typedef struct tcp_Sock_fds
{
    int Sock_fd;
    char name[128];
}tcp_Sock_fds;

#define MAX_LIST 20

//全局变量存储用户顺序表
tcp_Sock_fds Sock_fds[MAX_LIST];

int arr_len = 0;

//定义互斥锁
pthread_mutex_t lock;

int main(int argc, char const *argv[])
{
    //判断命令行参数
    if (argc < 2)
    {
        printf("参数错误:%s ip port\n",argv[0]);
        return -1;
    }

    // 给定默认ip

    char ip_str[128];

    if ( 3 != argc )
    {
        
        strcpy( ip_str , "192.168.91.182");
    }
    else{
        
        strcpy( ip_str , argv[2]);
    }
    
    // 1、创建套接字
    int Sock_fd = socket(AF_INET,SOCK_STREAM,0);
    if (-1 == Sock_fd)
    {
        ERRLOG("socket err");
        return -1;
    }
    // ​2、填充服务器网络信息结构体
    struct sockaddr_in Sock_addr;
    Sock_addr.sin_family = AF_INET;                 //选择IPV4
    Sock_addr.sin_port = htons(atoi(argv[1]));      //给定端口 atoi 将字符串转化为数字
    Sock_addr.sin_addr.s_addr = inet_addr(ip_str); //IP地址

    socklen_t Sock_size = sizeof(Sock_addr);
    // 3​、将套接字与服务器的网络信息结构体绑定
    if(-1 == bind(Sock_fd,(struct sockaddr *)&Sock_addr,Sock_size))
    {
        ERRLOG("bind err");
        return -1;
    }
    // ​4、将套接字设置城 监听状态
    if (-1 == listen(Sock_fd,5))
    {
        ERRLOG("listen err");
        return -1;
    }

    printf("有用户连接");

    pthread_t tid;
    int index = 0;

    //初始化锁
    pthread_mutex_init(&lock,NULL);

    while (1)
    {
        // ​5、阻塞等待客户端连接 accept
        int acc_fd = accept(Sock_fd,NULL,NULL);
        if (-1 == acc_fd)
        {
            ERRLOG("accept err");
            return -1;
        }
        if (arr_len >= MAX_LIST)
        {
            printf("已经满了\n");
            send(acc_fd,"已经满了",strlen("已经满了"),0);
            continue;
        }
        pthread_mutex_lock(&lock);

        //更新顺序表
        Sock_fds[arr_len].Sock_fd = acc_fd;
        strcpy(Sock_fds[arr_len].name,"新用户2580");

        index = arr_len;
        pthread_mutex_unlock(&lock);

        //创建线程
        pthread_create(&tid,NULL,Tcp_Server_func,(void *)&index);

        //线程分离
        pthread_detach(tid);

        arr_len++;
    }

    // ​7、关闭套接字  close
    close(Sock_fd);
    return 0;
}

void *Tcp_Server_func(void *arg)
{
    int index = *((int *)arg);
    
    char name[128];
    int Sock_fd;

    char buf[1024];
    char send_buf[2048];

    //初始化数据
    Sock_fd = Sock_fds[index].Sock_fd;
    strcpy(name,Sock_fds[index].name);
    while (1)
    {
        memset(buf,0,sizeof(buf));
        recv(Sock_fd,buf,sizeof(buf),0);
        pthread_mutex_lock(&lock);

        //修改名字
        if (NULL != strstr(buf,"set_name_"))
        {
            //写入姓名
            strcpy(Sock_fds[index].name,buf+9);
            //组装
            sprintf(buf,"修改姓名成功:%s",Sock_fds[index].name);
            send(Sock_fd,buf,strlen(buf),0);
        }
        //退出连接
        else if (!strcmp(buf,"quit"))
        {
            //组装
            sprintf(send_buf,"%s : %s ",Sock_fds[index].name,"退出成功");
            send(Sock_fd,send_buf,strlen(send_buf),0);
            break;
        }
        //转发群聊
        else
        {
            for (int i = 0; i < arr_len; i++)
            {
                //组装
                sprintf(send_buf,"%s : %s ",Sock_fds[index].name,buf);
                if (Sock_fd != Sock_fds[i].Sock_fd)
                {
                    send(Sock_fds[i].Sock_fd,send_buf,strlen(send_buf),0);
                }
            }
        }
        pthread_mutex_unlock(&lock);

        // 退出  关闭文件描述符   全局顺序表 就需要做删除  len --
        close(Sock_fd);
        //从顺序表中删除
        pthread_mutex_lock(&lock);

        for (int i = index; i < MAX_LIST; i++)
        {
            Sock_fds[i] = Sock_fds[i+1];
        }
        arr_len--;
        printf("连接已退出");
        pthread_mutex_unlock(&lock);
        return NULL;
    }
}